COMP2111
System Modelling and Design
Term 1, 2024

Notes (Week 9 Monday)

These are the notes I wrote during the lecture.

Very brief Hoare logic recap:


  Hoare triples

     {φ} P {ψ}

    φ precondition
    P program
    Ψ postcondition

    Reads: if φ is true in the initial state,
           then any state P can terminate in
           must satisfy ψ.

     { x contains the elements x_0,..,x_n }
       my_sorting_algorithm
     { x contains the elements x_0,..,x_n sorted in ascending order
     }

  Hoare logic:

   inference rules for proving Hoare triples

      ___________________  assign
      {φ[x:=e]} x:= e {φ}


      {φ} P {ρ}    {ρ} Q {ψ}
      _______________________  seq
         {φ} P; Q {ψ}


      {φ ∧ b} P {ψ}        {φ ∧ ¬b} Q {ψ}
      __________________________________ if
         {φ} if b then P else Q fi {ψ}


               {φ ∧ b} P {φ}
      __________________________________ while
         {φ} while b do P od {φ ∧ ¬b}


        φ ⇒ φ'    {φ'} P {ψ'}   Ψ' ⇒ Ψ
       ____________________________________ conseq
                  {φ} P {ψ}



  ⊢ {⊤} P {⊥}

  ^ it implies every other Hoare triple (about P) by the rule of consequence


  ⊢ {⊥} P {⊤}
  ^ this is the strictly most useless Hoare triple:
     it says "if you never run P, ⊤ will hold"


Two useful strats for finding loop invariants
 in this situation:

  i:=0
  m:=1
  while i < N do
    i := i + 1
    m := m × i
  od

 1: write a predicate that describes the
    current value of m

     If we can establish
        m = i!
     is a loop invariant

     Ask:
       does the postcondition follow?

       m = i! ∧ ¬i<N
       ⇒
       m = N!

       ^ no :(
         let's try to add conjuncts
         to make it work

      m = i! ∧ i ≤ N

      ^ this will work

      m = i! ∧ i ≤ N ∧ ¬N < i
      ⇒
      m = N!

 2: write a predicate that describes how
    to obtain N! from the current values
    of m and i

    (skip)


    {1 ≤ N}
    {1 = fib(1) ∧ 1 = fib(1+1) ∧ 1 ≤ N}        
    m := 1;
    {m = fib(1) ∧ 1 = fib(1+1) ∧ 1 ≤ N}
    n := 1;
    {m = fib(1) ∧ n = fib(1+1) ∧ 1 ≤ N}
    i := 1;
    {m = fib(i) ∧ n = fib(i+1) ∧ i ≤ N}
    while i < N do
      { m = fib(i) ∧ n = fib(i+1) ∧ i ≤ N ∧ i < N } *
      { n = fib(i+1) ∧ n+m = fib(i+1+1) ∧ i+1 ≤ N }
      t := m;
      { n = fib(i+1) ∧ n+t = fib(i+1+1) ∧ i+1 ≤ N }
      m := n;
      { m = fib(i+1) ∧ m+t = fib(i+1+1) ∧ i+1 ≤ N }
      n := m+t;
      { m = fib(i+1) ∧ n = fib(i+1+1) ∧ i+1 ≤ N }
      i := i+1
      { m = fib(i) ∧ n = fib(i+1) ∧ i ≤ N }
    od
    { m = fib(i) ∧ n = fib(i+1) ∧ i ≤ N ∧ ¬(i<N) }

    { m = fib(N) }


To prove the rule of consequence application at * we need to show that
   If    m = fib(i)        (1)
     and n = fib(i+1)      (2)
     and i ≤ N             (3)
     and i < N             (4)

   Then we need to prove:
      n = fib(i+1)      <-- exactly assumption (2)

      n+m = fib(i) + fib(i+1) =  (by 1,2)
          = fib(i+2) = (by definition of fib)
          = fib(i+1+1)   (cf. Russel & Whitehead)


      i+1 ≤ N   (immediate from i < N)


In assignment 1, there was an exercise where we modelled a connect 5
program as a relation between initial and final states.


The agenda:

  define a way to *systematically* compute such pre-post-state relations
  for any program in 𝓛.

    ⟦P⟧     "the semantics of P", where P ∈ 𝓛

    ⟦P⟧ ⊆ S × S        where S is the set of all states


  A Hoare triple is provable if we can derive it using the inference rules of Hoare logic

     ⊢ {φ} P {Ψ}

  Given such a semantics, we can state what it means for a Hoare triple
   to be valid:

        ⊧ {φ} P {Ψ}

        iff

        ∀s,t ∈ S. (s,t) ∈ ⟦P⟧ ∧ ⟦φ⟧s ⇒ ⟦Ψ⟧t



      ∀s,t ∈ S. (s,t) ∈ ⟦P⟧ ∧ φ(s) ⇒ Ψ(t)

Then we can state (and prove) e.g. *soundness* of Hoare logic:

  If ⊢ {φ} P {Ψ}  then ⊧ {φ} P {Ψ}

Or (TL;DR) we want to prove that Hoare logic "works", so we need to
define what "works" means ^above


   <  ⊆ ℕ × ℕ  (just bog-standard less-than on nats)

   (<); (<) =
   {(n,m) | ∃x. n < x ∧ x < m} =
   {(n,m) | n + 1 < m}

 (<)({1,2,3}) = {2,3,4,5,6,...}

 (<)({}) = {}


  ⟦b; P⟧   b a predicate, P a program

  =
  ⟦b⟧; ⟦P⟧
  =
  ⟦b⟧; ⟦P⟧
  =
  {(η,η') | ∃η''. (η,η'') ∈ ⟦b⟧ ∧ (η'',η') ∈ ⟦P⟧}
  =
  {(η,η') | ∃η''. η=η'' ∧ ⟦b⟧η = true ∧ (η'',η') ∈ ⟦P⟧}                                           

  =
  {(η,η') | ⟦b⟧η = true ∧ (η,η') ∈ ⟦P⟧}


  ⟦b⟧; ⟦P⟧ intuitively:
           the possible results of running P,
           but with b as an extra precondition


 R* is the least set defined by the following rules:


                 (x,y) ∈ R   (y,z) ∈ R*
  ___________    ____________________
  (x,x) ∈ R*         (x,z) ∈ R*


 We defined ⟦P⟧

 using three equations and one inference rule

      (η,η') ∈ ⟦x := e⟧    if   η' = η[x ↦ ⟦e⟧η]

      ⟦P; Q⟧ = ⟦P⟧; ⟦Q⟧

      ⟦if b then P else Q fi⟧ = ⟦b; P⟧ ∪ ⟦¬b; Q⟧

      ⟦while b do P od⟧ = ⟦b; P⟧*; ⟦¬b⟧

2024-04-19 Fri 10:38

Announcements RSS